Complete Notes

Object-oriented design is not a formal process. It's set of ideas and techniques to incorporate into your own process. It'll allow you to build better and more complex applications.

Procedural Programming Paradigm
Solves a problem from top to Bottom

OOP
Solves a problem using objects

Learn object-oriented design principles (linkedin.com)

There's no code in here. It's basically a way for us to understand how to "THINK" in an OOP way
It also allows you to understand how to communicate OOP to those who doesn't understand CODE

OOP is good for long term scalable projects.
You will often not see the benefits of OOP in short projects
the real value of object orientation will appear as your projects grow in scale and require changes.
But for large projects, the verbosity tradeoff is compensated with the organization of code

Definition - Object

To ask what's an object in a computer program, start by asking,
What's an object in the real world?

A mug is an object.
Are these two similar mugs (white mug1, white mug2) the same object?
^--> No, although they're similar mugs, they're not the same mug.
For example,
filling mug1 with coffee DOESN'T mean mug2 gets filled.
mug1 and mug2 separate objects,
each with its own existence and inherent properties/attributes that describe its current state.
Every object in a computer program is self-contained so it has its own identity separate from other objects, its own attributes to describe its current state and its own behaviors, the things it can do

It's possible for one object to contain other objects. I can talk about your phone as a thing in the real world so I can think of it as a computing object with attributes like color, size, and weight. In addition to that, your cellphone has behaviors. It can ring, and it can send text messages. - But the mug can't ring or text. So those behaviors are specific to my cellphone object. - Right, and I wouldn't try to use your cellphone to hold coffee.

Identity, attributes, and behaviors.
Those are the three things that describe objects in an object-oriented programming language.

Identifying if something should be represented as an Object

Figuring out if something in your application should be represented as an object.
That's easy when your application needs something like a mug, a person, or a document.
But what if you're building an event management application?
? Would an event be an object?
Well, just ask yourself, is it a noun? Nouns are things, people, places, and ideas or concepts.

Classes

Objects don't just magically appear in a program.
We have to create them, and we do so from classes.

A class is the detailed description, the definition, the template of what an object will be.
==but it isn't the object itself. ==

So, to create objects, I need the class first.

Classes are like our collection of cookie cutters.
This particular cutter would be the class to create circular cookies.
It defines how the cookie will look.
But the cutter itself is not a cookie.
And we only need this one cutter to create a tray full of round cookies, each a separate object ready for the oven.
Remember that the class always comes first. You can't make round cookies without the circular cutter.

So let's look at an example using our round cookie class:

  • Name on top,
  • attributes in the middle,
  • behaviors on the bottom.

Although the class says that each round cookie will have a size, a color, and possibly icing,
it doesn't specify the actual values for size, color, and icing. It's just providing a definition.

Definition - Instantiation

But, after defining the class,
I can create objects based on it through a process called instantiation.
And it's called that because each object I create is an instance of that particular class.

Each instances or data has its own attributes, so whatever I do with object1, will never affect what object2 will do.

3 Components of Class in OOP

Now you might encounter other, somewhat interchangeable, terms for these words.
Now, there are three components that make up a class in object-oriented programming.

Name - Type

Each class has a name, literally what is it? For example, a round cookie.
Instead of name, you might see type, because each class creates objects of a particular type.

Attributes - Properties

A class can have attributes to describe that object, such as weight, color and whether or not the cookie has icing. And as we talked about earlier, you might also see attributes referred to as properties, or more generically as data.

Behaviors - Operations

And it can have behaviors, the things that object can do, like decorate or consume.
And behaviors are also referred to as operations.

Method

When we actually write those behaviors as code, they're typically called a method
A method is a block of code or procedure that can be called to perform some action, and it may return a value.

What's the difference between methods and functions?
Methods are basically functions with the key difference that
-> methods are defined as part of a class. So they're included in any object in that class.

And, since methods exist as part of an object,
they can only access data that is known to that object.

Abstraction

  • Abstraction allows us to focus on essential aspects while hiding implementation complexities.
  • It’s akin to using a coffee machine: You don’t need to understand its internal workings to brew a cup of coffee. The machine abstracts away these details, providing a simple interface for interaction.
  • It's akin to a light switch, you don't need to understand how it works in order for it to work
    you just flip the switch, that's it.

Encapsulation

  1. Principles of encapsulation: An object should not make anything about itself available except what is absolutely necessary for other parts of the application to work. This is a concept referred to as 'black boxing'. I'm closing off the inner workings of the cookie jar and only revealing specific inputs and outputs. You don't need to know how the 'request cookie' method is implemented under the hood to use it.

  2. One of the main benefits with object orientation is that it allows us to more safely change the way the object works without changing the rest of the application. Perhaps, when I first wrote my cookie jar class,

Practical Examples as to why Encapsulation is used

  1. Restrict access to some of the object's components.
    When I create an instance of my cookie jar,
    I don't want you or any other part of my application to be able to reach in and directly change the number of cookies.
    If I let you directly change things, like the number, you might unknowingly change it to something invalid, like a negative one. That value doesn't make sense for the number of cookies and might cause my program to crash.

  2. Safely change how object works without changing the rest of the application
    I represented the total number of cookies as a single value. Then, later on, I decide to use three separate values to keep track of each type of cookie individually. Since I hid those attributes, I don't have to worry about breaking the other 20 parts of my application that have been using the 'request cookie' method to grab cookies. I'll just need to modify the 'request cookie' method and the class to handle the change.

Why Hide your own Code

Well, if you're the person writing these classes, why would you want to hide your own code?

  • It's not about being secretive.
  • It's about reducing dependencies between different parts of the application.
  • Change in one place won't cause a domino effect and require multiple changes elsewhere.

Inheritance

Inheritance enables a new class to receive or inherit the attributes and methods of existing classes using the same implementation which is a great form of code reuse.

Let's say for example I want to model the characters present in a bakery.

Class: Customers Class: Employee
name name
phone number phone number
updateContact() retire()

PROBLEM: Redundancy ABOVE
SOLUTION: Use Inheritance below
“inheritance.png” could not be found.
Person(super/parent class)
^-- Customer(sub/child class)
Employee(sub/child class)

All sub/child class automatically gets everything (attributes/behaviors) in the parents class.

Polymorphism

Simply means having many forms.
And appropriately enough, there are multiple forms of polymorphism.

Dynamic or run-time polymorphism,

Allows us to access methods using the same interface on different types of objects that may implement those methods in different ways.

Think of this basic coffee maker as a class with a method to brew coffee.
The input parameters for that brew method are a scoop of ground coffee beans and water. I wait a bit for it to brew and the output is a fresh cup of hot coffee. - I prefer to use a different type of coffee maker. A French press. My French press also has a brew method with the exact same inputs and outputs as Baron's basic coffee maker. I input a scoop of ground coffee and some water. Then after a little while, I press down the plunger and the output is a fresh cup of hot coffee. - Now, although these two coffee makers have the exact same type of inputs and outputs, the way that they brew is very different. My coffee maker uses a filter whereas Olivia's French press strains the coffee with a metal screen. - And although the outputs we received are the same type of object, a cup of coffee, their attributes may have some different values. When it comes to taste, my French press coffee is better. - Now, when it comes to actually implementing this type of polymorphism in code, there are several ways it could be done. Olivia's fancy FrenchPress could inherit all of the attributes and methods from my BasicCoffeeMaker. But then, it replaces the brew method it inherited from the BasicCoffeeMaker through a process called overriding. That allows the FrenchPress to redefine its own unique version of the brew method. - Or perhaps both of these coffee makers inherit from the same abstract class with an abstract brew method. - Or they both agree to implement the same interface. Inheritance, abstract classes, and interfaces are all possible implementations of polymorphism that we'll cover later on. The benefit of dynamic polymorphism here is that it enables me to use any form of coffee maker as long as it has a brew method that takes coffee grounds and water as inputs and returns a cup of coffee. - Even a really fancy coffee maker like this one? - Well, I've never seen one of those before, but if it has that brew method, I can use it. The other common form of polymorphism is called static or compile-time polymorphism. And it uses a feature of many object-oriented programming languages called method overloading, not to be confused with method overriding. Overloading allows you to implement multiple methods within a class that have the same name, but a different set of input parameters. If I give the brew method of the French press, coffee and water as input arguments, I'll get back a cup of coffee. But if I change the type of inputs, from coffee and water to tea leaves and water, that's a different set of parameters so the French press will execute a different version of the brew method that gives me back a cup of hot tea. Brew with coffee and water and brew with tea and water are two different methods with two different signatures. And the FrenchPress will automatically execute the appropriate one depending on what you give it. - [Olivia] You can also have variations of the method with different numbers of input parameters. I could implement a version of the brew method that takes three inputs, coffee and tea, and water. - You could do that, but I'm not sure you'd want to drink what you get out. In most cases, those overloaded methods will provide different, but very similar functionality. So those are the different forms of polymorphism. Defining different classes that can be used with the same interface. - Or overloading a method from the same class that can take different sets of parameters.

Analysis, design, and programming

When you see the words object-oriented, there's usually another word right beside it, object oriented programming, object oriented design, or object oriented analysis. These are all connected and refer to the idea that to develop any piece of software, you need to do three things, understand your problem, plan your solution, and finally, build it, or rather, analysis, design, and programming. Although they're listed as two separate steps, analysis and design are usually talked about together because they encompass everything that should happen before you write a single line of code. Analysis answers the question what do you need to do? What's the problem you're trying to solve? And design figures out how you're going to do it. In this course, we'll go through an entire object oriented analysis and design process to produce the deliverables, the conceptual design that you, or maybe a separate team of programmers, can take and use to build a solution. - Conceptual is the key word here. We won't be writing any code. - What about drawing diagrams? - Sure. - Sketches on a whiteboard? - Those are great.

For this course, we'll follow a typical five-step approach. Start by gathering requirements to figure out what our application needs to do. Really flesh out the problem you're trying to solve. After that, describe the application. Build a narrative in plain, conversational language for how people will use it. Step three involves identifying the most important objects, which is the starting point for identifying actual classes. Once those objects have been identified, formally describe the interactions between them, understanding each object's responsibilities, the behaviors they need to have, and when they interact with other objects. And finally, create a class diagram, which serves as the main output from the five-step process. The class diagram is a visual representation of the classes in the application, and creating it is where the object oriented principles like inheritance and polymorphism really come into play. We'll be diving into each of these steps in more detail, and we'll cover different techniques that you can use for each one.